#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "log.h"
#include "drawingboard.h"
#include "gpu.h"
#include "gpu_global.h"
#include <QFileInfo>
#include <QLabel>
#include <QPixmap>
#include <QImage>

Point p1, p2, p3;
math::vec4f pos1;
math::vec4f pos2;
math::vec4f pos3;

math::Mat4f modelMatrix;
math::Mat4f viewMatrix;
math::Mat4f perspectiveMatrix;
math::Mat4f screenMatrix;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    initUI();
    initData();
    initTimer();
    /*
    GpuInstance->drawLine(Point(50,50,Color(0,0,255)),Point(300,300,Color(0,255,0)));
    mp_drawingBoard->updateBoard(GpuInstance->getPixmap());

    GpuInstance->clearPixmap();

    GpuInstance->drawTriangle(Point(50,50,Color(178,34,34)), //红
                              Point(190,190,Color(0,205,0)), //绿
                              Point(550,10,Color(0,0,255))); //蓝
    mp_drawingBoard->updateBoard(GpuInstance->getPixmap());

    GpuInstance->clearPixmap();

    QString path = QFileInfo("./Image/Image1.jpg").absoluteFilePath();
    GpuInstance->drawImage(path.toStdString().c_str());
    mp_drawingBoard->updateBoard(GpuInstance->getPixmap());

    GpuInstance->clearPixmap();

    Point p1;
    p1.x = 0;
    p1.y = 0;
    p1.color = Color(255, 0, 0, 255);
    p1.uv = math::vec2f(1.0f, 1.0f);

    Point p2;
    p2.x = 400;
    p2.y = 800;
    p2.color = Color(0, 255, 0, 255);
    p2.uv = math::vec2f(1.5f, 2.0f);

    Point p3;
    p3.x = 800;
    p3.y = 0;
    p3.color = Color(0, 0, 255, 255);
    p3.uv = math::vec2f(2.0f, 1.0f);

    GpuInstance->setBilinearEnable(true);
    GpuInstance->setTextureWrap(TEXTURE_WRAP::TW_MIRROR);

    QString path2 = QFileInfo("./Image/Image1.jpg").absoluteFilePath();
    GpuInstance->drawUVTriangle(p1,p2,p3,path2.toStdString().c_str());
    mp_drawingBoard->updateBoard(GpuInstance->getPixmap());
    */
}

MainWindow::~MainWindow()
{
    if(m_timer.isActive())
    {
        m_timer.stop();
    }

    delete ui;
}

void MainWindow::initUI()
{
    ui->statusBar->hide();
    this->resize(1200,900);
    mp_drawingBoard = new DrawingBoard;
    ui->BoardUI->layout()->addWidget(mp_drawingBoard);

}

void MainWindow::initTimer()
{
    connect(&m_timer, &QTimer::timeout, [=]{

        m_angle += 0.01f;
        m_cameraPos += 0.01f;

        GpuInstance->clearPixmap();
        GpuInstance->setBilinearEnable(true);
        GpuInstance->setTextureWrap(TEXTURE_WRAP::TW_MIRROR);

        getChangeTrianglePoint(p1,p2,p3);
        GpuInstance->drawTriangle(p1,p2,p3);
        mp_drawingBoard->updateBoard(GpuInstance->getPixmap());
    });

    m_timer.start(1);
}

void MainWindow::initData()
{
    int WIDTH = 800;
    int HEIGHT = 600;

    p1.color = Color(255, 0, 0, 255);
    p1.uv = math::vec2f(0.0f, 0.0f);

    p2.color = Color(0, 255, 0, 255);
    p2.uv = math::vec2f(1.0f, 1.0f);

    p3.color = Color(0, 0, 255, 255);
    p3.uv = math::vec2f(1.0f, 0.0f);

    pos1 = {-1.5f, 0.0f, 0.0f, 1.0f};
    pos2 = {1.5f, 0.0f, 0.0f, 1.0f };
    pos3 = {0.0f, 2.0f, 0.0f, 1.0f };

    //透视投影
    perspectiveMatrix = math::perspective<float>(60.0f, (float)WIDTH / (float)HEIGHT, 0.1f, 100.0f);
    screenMatrix  = math::screen<float>(WIDTH, HEIGHT);

}

void MainWindow::getChangeTrianglePoint(Point &p1, Point &p2, Point &p3)
{
    //模型变换(绕y轴旋转)
     modelMatrix = math::rotate(math::Mat4f(1.0f), m_angle, math::vec3f{ 0.0f, 1.0f, 0.0f });

    //模拟摄像机往后退（z值增加）
    auto cameraModelMatrix = math::translate(math::Mat4f(1.0f), math::vec3f{ 0.0f, 0.0f, m_cameraPos});

    //视图矩阵
    viewMatrix = math::inverse(cameraModelMatrix);

    auto temp = viewMatrix;

    //mvp矩阵相乘
    auto sp1 = perspectiveMatrix * viewMatrix * modelMatrix * pos1;
    auto sp2 = perspectiveMatrix * viewMatrix * modelMatrix * pos2;
    auto sp3 = perspectiveMatrix * viewMatrix * modelMatrix * pos3;

    //透视除法（此处故意设计z！=0）
    sp1 /= sp1.m_w;
    sp2 /= sp2.m_w;
    sp3 /= sp3.m_w;

    //屏幕空间
    sp1 = screenMatrix * sp1;
    sp2 = screenMatrix * sp2;
    sp3 = screenMatrix * sp3;

    p1.x = sp1.m_x;
    p1.y = sp1.m_y;

    p2.x = sp2.m_x;
    p2.y = sp2.m_y;

    p3.x = sp3.m_x;
    p3.y = sp3.m_y;

}


